package site.fantasycube.blog.util.redis.impl;


import cn.hutool.core.util.RandomUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import site.fantasycube.blog.util.redis.IRedisCache;

import java.util.StringJoiner;
import java.util.concurrent.TimeUnit;

/**
 * @author 幻&乐
 * @Date 2021/12/26
 * 描述 Redis操作服务层
 */
@Component
public class RedisCacheImpl implements IRedisCache {

    private RedisTemplate redisTemplate;

    @Value("${blog.time.out}")
    private Integer timeOut;

    @Autowired
    public void setRedisTemplate(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 描述： 设置一个@Value("${blog.time.out}")分钟过期的验证码code
     *
     * @param email 发送验证码的邮箱
     * @return String 验证码（邮箱+当前时间）例如huanan@qq.com:1231342
     * @author 幻&乐
     * @Date 2021/12/28 15:14
     **/
    @Override
    public String setMsg(String email) {
        StringJoiner joiner = new StringJoiner(":");
        Long time = System.currentTimeMillis();
        //拼接邮箱和时间
        joiner.add(email).add(time.toString());
        //随机获取10个
        String str = RandomUtil.randomStringWithoutStr(10, "oO0、lL1、q9Q、pP");
        redisTemplate.opsForValue().set(str, joiner.toString(), timeOut, TimeUnit.MINUTES);
        return str;
    }

    /**
     * 描述： 查询当前code是否超时
     *
     * @param code 验证码
     * @return 是否过期(true过期)
     * @author 幻&乐
     * @Date 2021/12/28 15:36
     **/
    @Override
    public Boolean chackMsg(String code) {
        Object o = redisTemplate.opsForValue().get(code);
        if (o == null) {
            return true;
        }
        Long oldTime = Long.valueOf(o.toString().split(":")[1]);
        Long nowTime = System.currentTimeMillis();
        if (nowTime - oldTime > timeOut * 60 * 1000) {
            return true;
        }
        //校验完成删除缓存
        del(code);
        return false;
    }


    /**
     * 描述： 设置永不过期的缓存
     *
     * @param key
     * @param value
     * @author 幻&乐
     * @Date 2021/12/26 3:07
     **/
    @Override
    public void setValue(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 描述： 为某一个key设置过期时间
     *
     * @param key  key
     * @param time 过期时间（分钟）
     * @return 是否成功
     * @author 幻&乐
     * @Date 2021/12/26 22:08
     **/
    @Override
    public Boolean setOutTime(String key, Long time) {
        return redisTemplate.expire(key, time, TimeUnit.MINUTES);
    }

    /**
     * 描述： 设置过期时间的缓存
     *
     * @param key   key
     * @param value value
     * @param time  过期时间，默认为分钟
     * @author 幻&乐
     * @Date 2021/12/26 3:15
     **/
    @Override
    public void setValue(String key, Object value, Long time) {
        redisTemplate.opsForValue().set(key, value, time, TimeUnit.MINUTES);
    }

    /**
     * 描述： 获取存放的实体类
     *
     * @param key key
     * @return object 实体类
     * @author 幻&乐
     * @Date 2021/12/26 3:22
     **/
    @Override
    public Object getValue(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * 描述： 根据key删除缓存
     *
     * @param key key
     * @return 是否成功
     * @author 幻&乐
     * @Date 2021/12/26 3:38
     **/
    @Override
    public Boolean del(String key) {
        return redisTemplate.delete(key);
    }

    /**
     * 描述： 对该key下的值进行减法
     *
     * @param key   key
     * @param count 减去的数量
     * @return 减完之后的值
     * @author 幻&乐
     * @Date 2021/12/26 3:28
     **/
    @Override
    public Long decrement(String key, Long count) {
        return redisTemplate.opsForValue().decrement(key, count);
    }

    /**
     * 描述： 对该key下的值进行加法
     *
     * @param key   key
     * @param count 增加的值
     * @return 增加之后的值
     * @author 幻&乐
     * @Date 2021/12/26 3:31
     **/
    @Override
    public Long increment(String key, Long count) {
        return redisTemplate.opsForValue().increment(key, count);
    }

    /**
     * 描述： 设置大小key缓存
     *
     * @param key1  key1
     * @param key2  key2
     * @param value 实体类
     * @author 幻&乐
     * @Date 2021/12/26 3:20
     **/
    @Override
    public void setHash(String key1, String key2, Object value) {
        redisTemplate.opsForHash().put(key1, key2, value);
    }

    /**
     * 描述： 大小key获取缓存值
     *
     * @param key1 大key
     * @param key2 小key
     * @return 对象
     * @author 幻&乐
     * @Date 2021/12/28 14:36
     **/
    @Override
    public Object getHash(String key1, String key2) {
        return redisTemplate.opsForHash().get(key1, key2);
    }

    /**
     * 描述： 删除hashkey
     *
     * @param key1 大key
     * @param key2 小key，可以有多个
     * @author 幻&乐
     * @Date 2021/12/28 14:39
     **/
    public void delHash(String key1, String... key2) {
        redisTemplate.opsForHash().delete(key1, key2);
    }

    /**
     * 描述： 设置锁
     *
     * @param lockKey 锁key
     * @param value   值
     * @param time    时间；默认毫秒
     * @return 是否设置成功
     * @author 幻&乐
     * @Date 2021/12/26 3:46
     **/
    @Override
    public Boolean setLock(String lockKey, Object value, Long time) {
        return redisTemplate.opsForValue().setIfAbsent(lockKey, value, time, TimeUnit.MILLISECONDS);
    }
}
